vtd: boolean boot parameter to allow inclusive mapping of all memory below 4GB
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 2 Mar 2009 11:23:23 +0000 (11:23 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 2 Mar 2009 11:23:23 +0000 (11:23 +0000)
Signed-off-by: Ross Philipson <ross.philipson@citrix.com>
xen/arch/ia64/xen/mm.c
xen/arch/x86/mm.c
xen/arch/x86/setup.c
xen/drivers/passthrough/vtd/dmar.c
xen/drivers/passthrough/vtd/iommu.c
xen/drivers/passthrough/vtd/x86/vtd.c
xen/drivers/video/vga.c
xen/include/xen/mm.h

index 97deeddfe8cdca5d49b2d35222afebf3d2f4e921..c98272a0b3debbfc139a380065ea26763bd79692 100644 (file)
@@ -3236,9 +3236,56 @@ int get_page_type(struct page_info *page, unsigned long type)
     return 1;
 }
 
-int page_is_conventional_ram(unsigned long mfn)
+int page_is_ram_type(unsigned long mfn, unsigned long type)
 {
-    return (efi_mem_type(pfn_to_paddr(mfn)) == EFI_CONVENTIONAL_MEMORY);
+    u32 mem_type = efi_mem_type(pfn_to_paddr(mfn));
+
+    if (type & RAM_TYPE_CONVENTIONAL)
+    {
+        switch (mem_type)
+        {
+        case EFI_BOOT_SERVICES_CODE:
+        case EFI_BOOT_SERVICES_DATA:
+        case EFI_LOADER_CODE:
+        case EFI_LOADER_DATA:
+        case EFI_CONVENTIONAL_MEMORY:
+            return 1;
+        default:
+            break;
+        }       
+    }
+    if (type & RAM_TYPE_RESERVED)
+    {
+        switch (mem_type)
+        {
+        case EFI_RUNTIME_SERVICES_CODE:
+        case EFI_RUNTIME_SERVICES_DATA:
+        case EFI_RESERVED_TYPE:
+        case EFI_MEMORY_MAPPED_IO:
+        case EFI_MEMORY_MAPPED_IO_PORT_SPACE:
+        case EFI_PAL_CODE:
+            return 1;
+        default:
+            break;
+        }
+    }
+    if (type & RAM_TYPE_ACPI)
+    {
+        switch (mem_type)
+        {
+        case EFI_ACPI_RECLAIM_MEMORY:
+        case EFI_ACPI_MEMORY_NVS:
+            return 1;
+        default:
+            break;
+        }
+    }
+    else if (type & RAM_TYPE_UNUSABLE)
+    {
+        return (mem_type == EFI_UNUSABLE_MEMORY);
+    }
+
+    return 0;
 }
 
 
index 9e288e44e75146e84342e80204fcb96502c90de8..cbbe2e0abc6311802c74b021dc885e665bb8229b 100644 (file)
@@ -279,15 +279,39 @@ void __init arch_init_memory(void)
     subarch_init_memory();
 }
 
-int page_is_conventional_ram(unsigned long mfn)
+int page_is_ram_type(unsigned long mfn, unsigned long mem_type)
 {
     uint64_t maddr = pfn_to_paddr(mfn);
     int i;
 
     for ( i = 0; i < e820.nr_map; i++ )
     {
-        if ( (e820.map[i].type == E820_RAM) &&
-             (e820.map[i].addr <= maddr) &&
+        switch ( e820.map[i].type )
+        {
+        case E820_RAM:
+            if ( mem_type & RAM_TYPE_CONVENTIONAL )
+                break;
+            continue;
+        case E820_RESERVED:
+            if ( mem_type & RAM_TYPE_RESERVED )
+                break;
+            continue;
+        case E820_UNUSABLE:
+            if ( mem_type & RAM_TYPE_UNUSABLE )
+                break;
+            continue;
+        case E820_ACPI:
+        case E820_NVS:
+            if ( mem_type & RAM_TYPE_ACPI )
+                break;
+            continue;
+        default:
+            /* unknown */
+            continue;
+        }
+        
+        /* Test the range. */
+        if ( (e820.map[i].addr <= maddr) &&
              ((e820.map[i].addr + e820.map[i].size) >= (maddr + PAGE_SIZE)) )
             return 1;
     }
index 996b52828a9c5751f586a927ae981eca5170b06a..be86447c5415285476a0630137dd88eaf4570dc3 100644 (file)
@@ -985,6 +985,9 @@ void __init __start_xen(unsigned long mbi_p)
 
     if ( opt_watchdog ) 
         watchdog_enable();
+    
+    if ( !tboot_protect_mem_regions() )
+        panic("Could not protect TXT memory regions\n");
 
     /* Create initial domain 0. */
     dom0 = domain_create(0, 0, DOM0_SSIDREF);
@@ -1037,9 +1040,6 @@ void __init __start_xen(unsigned long mbi_p)
     if ( xen_cpuidle )
         xen_processor_pmbits |= XEN_PROCESSOR_PM_CX;
 
-    if ( !tboot_protect_mem_regions() )
-        panic("Could not protect TXT memory regions\n");
-
     /*
      * We're going to setup domain0 using the module(s) that we stashed safely
      * above our heap. The second module, if present, is an initrd ramdisk.
index 946ade0101f120d526c5c3ebb51e07c57a5454ee..60d4a4e7778cc631663c3b3b376c510c472ffbff 100644 (file)
@@ -377,6 +377,19 @@ acpi_parse_one_rmrr(struct acpi_dmar_entry_header *header)
         return -EFAULT;
     }
 
+#ifdef CONFIG_X86
+    /* This check is here simply to detect when RMRR values are not properly represented in the 
+       system memory map and inform the user */
+    if ( (!page_is_ram_type(paddr_to_pfn(rmrr->base_address), RAM_TYPE_RESERVED))||
+         (!page_is_ram_type(paddr_to_pfn(rmrr->end_address) - 1, RAM_TYPE_RESERVED)) )
+    {
+        dprintk(XENLOG_WARNING VTDPREFIX,
+                "RMRR address range not in reserved memory base = %"PRIx64" end = %"PRIx64"; " \
+                "iommu_inclusive_mapping=1 parameter may be needed.\n",
+                rmrr->base_address, rmrr->end_address);
+    }
+#endif
+
     rmrru = xmalloc(struct acpi_rmrr_unit);
     if ( !rmrru )
         return -ENOMEM;
index 8f6f5959f92895fcec7f3bff194955fbaf751ed9..b41f9e7e9d1e292bee6df7e0565b89de4c97a3a3 100644 (file)
@@ -992,8 +992,6 @@ static int intel_iommu_domain_init(struct domain *d)
 
     if ( d->domain_id == 0 )
     {
-        extern int xen_in_range(paddr_t start, paddr_t end);
-
         /* Set up 1:1 page table for dom0 */
         iommu_set_dom0_mapping(d);
 
index d4678d43cfd0b15f1c247aaddf7020f9ca7ea45d..65fd5e189fb2e74f7cc13da878442b7f0ba4d4bd 100644 (file)
 #include "../dmar.h"
 #include "../vtd.h"
 
+/* iommu_inclusive_mapping: when set, all memory below 4GB is included in dom0 1-1 iommu mappings except xen and unusable regions */
+static int iommu_inclusive_mapping = 0;
+boolean_param("iommu_inclusive_mapping", iommu_inclusive_mapping);
+
 void *map_vtd_domain_page(u64 maddr)
 {
     return map_domain_page(maddr >> PAGE_SHIFT_4K);
@@ -153,9 +157,22 @@ void iommu_set_dom0_mapping(struct domain *d)
 
     for ( i = 0; i < max_page; i++ )
     {
-        /* Set up 1:1 mapping for dom0 for all RAM except Xen bits. */
-        if ( !page_is_conventional_ram(i) ||
-             xen_in_range(i << PAGE_SHIFT, (i + 1) << PAGE_SHIFT) )
+        /* Set up 1:1 mapping for dom0 */
+        if ( !page_is_ram_type(i, RAM_TYPE_CONVENTIONAL) )
+        {
+            /* Default it to use only conventional RAM areas and let RMRRs include needed reserved regions */
+            if (iommu_inclusive_mapping)
+            {
+                /* When set, the inclusive mapping maps in everything below 4GB except unusable ranges */
+                if ( (i >= 0x100000) || page_is_ram_type(i, RAM_TYPE_UNUSABLE) )
+                    continue;
+            }
+            else
+                continue;
+        }
+
+        /* Exclude Xen bits */
+        if ( xen_in_range(i << PAGE_SHIFT, (i + 1) << PAGE_SHIFT) )
             continue;
 
         tmp = 1 << (PAGE_SHIFT - PAGE_SHIFT_4K);
index 22db37430e4e041ab1509a39d92e68f8b6e1f228..e1828c1687190d839bf92add01afaa52d606d394 100644 (file)
@@ -79,7 +79,7 @@ void __init vga_init(void)
     switch ( vga_console_info.video_type )
     {
     case XEN_VGATYPE_TEXT_MODE_3:
-        if ( page_is_conventional_ram(paddr_to_pfn(0xB8000)) ||
+        if ( page_is_ram_type(paddr_to_pfn(0xB8000), RAM_TYPE_CONVENTIONAL) ||
              ((video = ioremap(0xB8000, 0x8000)) == NULL) )
             return;
         outw(0x200a, 0x3d4); /* disable cursor */
index da3b6d1f9d3a0c4c8ea198a3c48aeecada9bc324..fa6175178596f5f37a56f6d7c06ad3a81798d3fc 100644 (file)
@@ -273,8 +273,12 @@ unsigned long avail_scrub_pages(void);
 
 int guest_remove_page(struct domain *d, unsigned long gmfn);
 
-/* Returns TRUE if the whole page at @mfn is ordinary RAM. */
-int page_is_conventional_ram(unsigned long mfn);
+#define RAM_TYPE_CONVENTIONAL 0x00000001
+#define RAM_TYPE_RESERVED     0x00000002
+#define RAM_TYPE_UNUSABLE     0x00000004
+#define RAM_TYPE_ACPI         0x00000008
+/* Returns TRUE if the whole page at @mfn is of the requested RAM type(s) above. */
+int page_is_ram_type(unsigned long mfn, unsigned long mem_type);
 
 extern unsigned long *alloc_bitmap;    /* for vmcoreinfo */